package tjs.study.notes.dotest.proxy.jdk;//package tjs.study.notes.dotest.proxy.jdk;


import sun.misc.ProxyGenerator;
import tjs.study.notes.dotest.proxy.service.IUserService;
import tjs.study.notes.dotest.proxy.service.UserService;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * jdk动态代理的原理，构造一个类 继承Proxy(持有切面的引用)，实现目标接口
 * 所以，jdk只能代理接口，因为java是单继承的
 */
public class DoTest {

    /**
     * 1.先在此处打上条件断点
     * 断点条件：var1!=null&&var1[0].getName().indexOf("rederFeignApi")!=-1
     * {@link ProxyGenerator#generateProxyClass(java.lang.String, java.lang.Class[], int)}
     *
     * 2. 再在以下位置打上断点
     * 构造代理类： {@link sun.misc.ProxyGenerator#generateClassFile()}
     * 构造代理方法：{@link sun.misc.ProxyGenerator.ProxyMethod#generateMethod()}
     * 继承类：{@link Proxy}
     * 将代理class的字节数组转成class文件： DoTest.getFileByBytes(slot_1.toByteArray(),"UserService.class")
     *
     * 最终加入jvm是调用的Proxy#defineClass0,而非ClassLoder类下的
     * {@link java.lang.reflect.Proxy#defineClass0(java.lang.ClassLoader, java.lang.String, byte[], int, int)}
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        // 设置变量可以保存动态代理类，默认名称以 $Proxy0 格式命名  路径为根目录下+/com/sun/proxy
        System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//        System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");

        testNormal();

    }


    public static void testNormal() {

        UserService userServiceImpl = new UserService("test");
        ClassLoader classLoader = userServiceImpl.getClass().getClassLoader();
        Class[] interfaces = userServiceImpl.getClass().getInterfaces();
        InvocationHandler logHandler = new LogHandler(userServiceImpl);
//        Proxy.getProxyClass(classLoader, interfaces);
        IUserService proxy = (IUserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);
        IUserService proxy2 = (IUserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);

        //中间类只会生成一次
        System.out.println(proxy.getClass() == proxy2.getClass());//true

        // 调用代理的方法
        proxy.login();

//        Method[] methods = proxy.getClass().getMethods();
//        for (Method method : methods) {
//            System.out.println(method.getName());
//        }


    }

    public static void getFileByBytes(byte[] bytes, String fileName) {
        String filePath = "/Users/piangpiang/Documents/my-workspace/my-mayun/tjs-study-notes-test2/tjs-study-notes/tjs-study-notes/tjs-study-dotest/src/main/java/tjs/study/notes/dotest/proxy/jdk/agent";
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {// 判断文件目录是否存在
                dir.mkdirs();
            }
            file = new File(filePath + "/" + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}